package chaoyue.study.filter;

import chaoyue.study.domain.LoginUser;
import chaoyue.study.service.LoginService;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Objects;

/**
 * 实现自己的Token认证过滤器
 * 除登录外其他接口的请求都需要通过这个过滤器判断是否携带了Token信息
 * OncePerRequestFilter 是Spring提供的Filter实现，保证过滤器只执行一次
 * 过滤器需要手动加入到SpringSecurity的过滤器链中，并且需要放到最前面去执行
 */
@Slf4j
@Component
public class MyTokenAuthenticationFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 从Header中获取Token 如果没有token 交给后续的拦截器处理
        String token = request.getHeader("token");
        if (StringUtils.hasText(token)) {
            log.info("获取到Token -> {}", token);
            // 通过Token 获取用户信息
            LoginUser loginUser = LoginService.CACHE.get(token);
            if (!Objects.isNull(loginUser)) {
                log.info("当前用户 -> {}", loginUser);
                // 存入SecurityContextHolder 因为后面的过滤器都要从这里获取认证信息
                UsernamePasswordAuthenticationToken authenticationToken =
                        new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            } else {
                throw new RuntimeException("登录过期，请重新登录！");
            }
        }
        // 请求放行
        filterChain.doFilter(request, response);
    }
}
